perm filename TEMPL.SAI[PUB,ALS] blob sn#195747 filedate 1985-11-15 generic text, type C, neo UTF8
COMMENT ⊗   VALID 00011 PAGES
C REC  PAGE   DESCRIPTION
C00001 00001
C00003 00002	BEGOF("TEMPL")
C00004 00003	PUBLIC SIMPLE PROCEDURE TEMPL! $"#
C00005 00004	PUBLIC RECURSIVE PROCEDURE APPLYTOARGUMENTS(BOOLEAN DO!IT, PROCALL) $"#
C00009 00005	PUBLIC SIMPLE PROCEDURE DDONE(BOOLEAN RETURNS) $"#
C00012 00006	PUBLIC STRING SIMPLE PROCEDURE DEFN(BOOLEAN SUBSTVARIABLES,FORFILE INTEGER ARGS, IBASE) $"#
C00019 00007	PUBLIC SIMPLE PROCEDURE DMACRO(INTEGER ODDONE) $"#
C00022 00008	PUBLIC SIMPLE PROCEDURE DREPEAT $"#
C00023 00009	PUBLIC RECURSIVE STRING PROCEDURE PROCSTATEMENT $"#
C00024 00010	PUBLIC SIMPLE PROCEDURE WARNLONG(STRING SEGM, MESG) $"#
C00025 00011	FINISHED
C00026 ENDMK
C⊗;
BEGOF("TEMPL")

COMMENT

MACROs, PROCEDUREs, REPEATs, counter and response templates. If you
don't find here what you are looking for, try file RESPS for
responses, SORCE for source switching, CNTRS for counters.

;

PROCEDURES
PUBLIC SIMPLE PROCEDURE TEMPL! ;$"#
BEGIN "TEMPL!"
MAXTEMPLATE ← 5000 ; TES 8/19/74 ;
END "TEMPL!" ;
PUBLIC RECURSIVE PROCEDURE APPLYTOARGUMENTS(BOOLEAN DO!IT, PROCALL) ;$"#
BEGIN TES 8/19/74 EXTRACTED FROM PASS TO HANDLE PROCEDURES AS WELL AS MACROS ;
BOOLEAN WASLPAR, DUMSEMI ;
INTEGER MACIX, MACSYM, ARGS, ARG, ARGSYM, NAMES, K ;
MACIX ← IX ; MACSYM ← SYMB ; ARGS ← NUMARGS(MACIX) ; DUMSEMI ← FALSE ;
IF ARGS THEN
	BEGIN "SCAN ARGS"
	STRING ARRAY ACTUAL[1:ARGS] ;
	IF  NOT (WASLPAR ← NEXTSCH(<(>)) THEN INPUTSTR ← LIT!ENTITY&LIT!TRAIL&INPUTSTR ;
	comment , Back up. Pretend just passed comma. ; THISWD ← "," ; EMPTYTHAT ;
	NAMES ← NAMEPAR(MACIX) ; comment bit table for name parameters ;
	FOR ARG ← 1 THRU ARGS DO
		BEGIN "EACH ACTUAL"
		IF  NOT ITSCH(<,>) THEN ACTUAL[ARG] ← NULL comment , omitted argument;
		ELSE	BEGIN	RD(TO!VISIBLE) ;
			IF NAMES LAND TWO(ARGS-ARG) = 0 THEN
				BEGIN PASS ; ACTUAL[ARG] ← E(NULL, NULL&'0) ; END
			ELSE	BEGIN "CALL BY NAME"
				IF BRC NEQ """" THEN
				 BEGIN comment , Unquoted Call-By-Name ;
				 IF (K←BRC)="|" THEN RD(ONE!CHAR) ;
				 ACTUAL[ARG]←RD(IF K="|" THEN TO!VBAR!SKIP
					ELSE IF WASLPAR THEN TO!COMMA!RPAR ELSE TO!TERQ!CR) ;
				 IF BRC=CR AND  NOT WASLPAR THEN
					BEGIN comment force a semicolon ;
					INPUTSTR ← ";" & INPUTSTR ;
					DUMSEMI ← TRUE ;
					END ;
				 PASS ;
				 END
				ELSE	BEGIN PASS ; ACTUAL[ARG]←E(NULL,0) END ;
				END "CALL BY NAME"
			END
		END "EACH ACTUAL" ;
	WHILE ITSCH(<,>) DO
		BEGIN
		WARN("=",<"Too Many Arguments to "&SYM[MACSYM]>) ;
		PASS ; E(NULL, 0) ;
		END ;
	IF ITSCH(<)>) AND WASLPAR THEN BEGIN comment  Easy case; END
	ELSE	BEGIN
		IF WASLPAR THEN WARN("=",<"Missed ) After Macro Call">) ;
		comment Back Up -- SWICH only saves THATWD ;
		IF THATISFULL THEN comment Unlikely; INPUTSTR ← LIT!ENTITY&LIT!TRAIL&INPUTSTR ;
		IF THISISFULL AND  NOT DUMSEMI THEN BEGIN THATWD ← LIT!ENTITY ← THISWD ;
			LIT!TRAIL ← IF THISTYPE<-1 THEN NULL ELSE SP ;
			THATTYPE ← THISTYPE MIN 0 END ELSE EMPTYTHAT ;
		END ;
	IF PROCALL THEN SWICH("RETURN(NULL);;",-2-BLNMS,0) ; TES 8/20/74 ;
	IF DO!IT THEN
		BEGIN "STACK ARGUMENTS"
		IF LAST + ARGS > SIZE THEN GROWNESTS ;
		FOR ARG ← 1 THRU ARGS DO
			SNEST[LAST + ARG] ← ACTUAL[ARG] ;
		LAST ← LAST + ARGS ; 
		END "STACK ARGUMENTS" ;
	END "SCAN ARGS" ;
IF PROCALL AND NOT ARGS THEN SWICH("RETURN(NULL);;",-2-BLNMS,0) ; TES 8/20/74 ;
IF DO!IT THEN SWICH(SSTK[BODY(MACIX)], -1, ARGS)
ELSE BEGIN THISWD ← "7" ; THISTYPE ← -1 END ; COMMENT, Replace by NULL ("") ;
END "APPLYTOARGUMENTS" ;
PUBLIC SIMPLE PROCEDURE DDONE(BOOLEAN RETURNS) ;$"#
BEGIN TES 8/14/74 (DONE) 8/19/74 (RETURN);
INTEGER B ; STRING VAL ; BOOLEAN GOT ;
PASS ;
IF ON THEN
IF NOT RETURNS AND DEEPREPEATS=0 THEN WARN(NULL,"Ignored a DONE without a repeat")
ELSE IF RETURNS AND DEEPPROCEDURES=0 THEN WARN(NULL, "Ignored a RETURN not in a PROCEDURE")
ELSE
BEGIN
IF RETURNS THEN
	BEGIN
	DEEPPROCEDURES ← DEEPPROCEDURES - 1 ;
	IF ITSCH(<(>) THEN
		BEGIN COMMENT VALUE TO RETURN ;
		PASS ;
		VAL ← E(NULL, NULL) ;
		IF NOT ITSCH(<)>) THEN WARN(NULL, <"Missed ) after RETURN">) ;
		END
	ELSE VAL ← NULL ;
	END
ELSE DEEPREPEATS ← DEEPREPEATS - 1 ;
EMPTYTHIS ; EMPTYTHAT ; INPUTSTR ← NULL ;
DO	BEGIN
	WHILE LAST AND CHANSCAN(LAST) > -2 DO
		INPUTSTR ← SWICHBACK ;
	GOT ← RETURNS EQV EQU("RETURN(", STRSCAN(LAST)[1 TO 7]) ;
	STRSCAN(LAST) ← NULL ;
	IF NOT GOT THEN CHANSCAN(LAST)←-1 ;
	END UNTIL GOT ;
B ← -2 - CHANSCAN(LAST) ;
WHILE B<BLNMS DO
	CASE IF STARTS THEN 0 ELSE ENDCASE OF
		BEGIN
		BEGIN BLNMS←BLNMS-1 ; STARTS←STARTS-1 ; END ;
		BEGIN BLNMS←BLNMS-1 ; IF ENDBLOCK THEN WARN("=","Missed END")  END ;
		IF ENDBLOCK THEN WARN("=", "Missed END") ELSE
			BEGIN BLNMS←BLNMS-1 ; IF ENDBLOCK THEN WARN("=","Missed END")  END ;
		BEGIN BLNMS←BLNMS-1 ; IF ENDBLOCK THEN MYEND ← TRUE ELSE WARN("=","Extra END") END ;
		END ;
CHANSCAN(LAST) ← -1 ;
INPUTSTR ← SWICHBACK ;
PASS ;
IF RETURNS THEN PROCVALUE ← VAL ;
END ;
END "DDONE" ;
PUBLIC STRING SIMPLE PROCEDURE DEFN(BOOLEAN SUBSTVARIABLES,FORFILE; INTEGER ARGS, IBASE) ;$"#
BEGIN
STRING SEGMENT, IDENT, PSPCS, SPCS, FML, TXID, TX2 ;
INTEGER SINDX, I, DEEP, PGMKS, REQRS ;
LABEL FORMAL ;
IF ITSCH(;) THEN PASS ; DEFINING ← NOT FORFILE ; comment, makes RD include line nos in result ;
IF  NOT ITSCH(⊂) AND NOT(ITSCH($) AND NEXTSCH(<(>))
	THEN BEGIN WARN("=",<"Missed Horseshoe, ↑P,  OR $( in definition">) ; RETURN(NULL) END ;
DEEP ← 1 ; SINDX ← SHIGH ;
IF SHIGH+20>STSIZE THEN
	BEGIN
	SGROW(STBL,STBLIDA,STSIZE,100,"Definition") ;
	SMAKEBE(STBLIDA, STBL) ; ZEROSTRINGS(100, STBL[STSIZE-99]) ;
	END ;
EMPTYTHIS ; comment For page label switch in LABELREF ;
IF FORFILE THEN STBL[SINDX←SINDX+1] ← SRCLINE & "/" & SRCPAGE & TB & ALTMODE ;
IF EQU(INPUTSTR[1 for 2], RCBRAK&VT) THEN
	BEGIN
	STBL[SINDX ← SINDX + 1] ← CRLF & SRCLINE & "/" & SRCPAGE & TB ;
	INPUTSTR ← INPUTSTR[3 for ∞] ;
	END ;
PGMKS ← PAGEMARKS ; REQRS ← LAST ; TES 8/19/74 ;
WHILE DEEP DO
	BEGIN "DEF BODY"
	SEGMENT ← RD(DEFN!TABLE) ;
	IF BRC = "⊂" OR BRC="$" AND INPUTSTR="(" AND LOP(INPUTSTR)="(" THEN
		BEGIN DEEP ← DEEP + 1 ; SEGMENT ← SEGMENT & "⊂" ; END
	ELSE IF BRC = "⊃" OR BRC=")" AND INPUTSTR="$" AND LOP(INPUTSTR)="$" THEN
		BEGIN DEEP ← DEEP - 1 ;
		SEGMENT ← SEGMENT & (IF DEEP THEN "⊃" ELSE SP) ;
		END
	ELSE IF BRC = "∃" THEN SEGMENT ← SEGMENT & (IF DEEP>1 THEN BRC ELSE NULL) & RD(ONE!CHAR)
	ELSE IF LENGTH(TXID←BRC)  AND 
		(LDB(SPCODE(BRC))=LCURLY  OR 
		 LDB(SPCODE(BRC))=DOLLAR AND LDB(SPCODE(INPUTSTR))=LBRACK  AND 
			LENGTH(TXID←TXID&LOP(INPUTSTR))) THEN
		IF SUBSTVARIABLES THEN
		BEGIN "{..."
		SPCS ← TXID & RD(TO!VISIBLE) ;
		IDENT ← SCAN(INPUTSTR,ALPHA,DUMMY) ; PSPCS ← RD(TO!VISIBLE) ;
		IF BRC = RCBRAK OR BRC="]" AND INPUTSTR[2 FOR 1]="$"THEN
			BEGIN
			LOPP(INPUTSTR) ;
			IF BRC="]" THEN BEGIN TX2←"]$" ; LOPP(INPUTSTR) END ELSE TX2←RCBRAK ;
			SEGMENT ← SEGMENT &
			(IF FULSTR(IDENT) AND SIMLOOK(CAPITALIZE(IDENT))
			 AND SYMTYPE<MACROTYPE THEN  TES 11/29/73 ;
				IF SYMIX=IXPAGE THEN ALTMODE&"[@]"&
				 LABELREF(0,
					IF SYMBOL=SYMPAGE THEN CTR!CHRS(IXPAGE)
					ELSE PATT!CHRS(IXPAGE))
				ELSE EVALV(IDENT, SYMIX, SYMTYPE)
			ELSE SPCS & IDENT & PSPCS & TX2)
			END
		ELSE SEGMENT ← SEGMENT & SPCS & IDENT & PSPCS ;
		END "{..."
		ELSE SEGMENT ← SEGMENT & TXID
	ELSE IF BRC = RCBRAK THEN
		IF EQU(INPUTSTR[1 for 2], RCBRAK&VT) THEN ELSE SEGMENT ← SEGMENT & BRC
	ELSE IF LDB(FAMILY(BRC)) = LETTQ THEN
		BEGIN "LETTER"
		IDENT ← (BRC+0) & SCAN(INPUTSTR, ALPHA, BRC) ;
		FOR I ← 1 THRU ARGS DO IF EQU(FML←SYM[ITBL[IBASE+I]], TXID←CAPITALIZE(IDENT)) THEN
				FORMAL: BEGIN IDENT ← VT & I ; DONE END
			ELSE IF 1 LEQ LENGTH(TXID)-LENGTH(FML) LEQ 2 THEN
				BEGIN "MAYBE UNDERLINED"
				INTEGER L, R ;
				L ← IF IDENT="_" THEN 1 ELSE 0 ; R ← IF IDENT[∞ FOR 1]="_" THEN 1 ELSE 0 ;
				IF EQU(FML, TXID[1+L TO ∞-R]) THEN
					BEGIN
					IF L THEN SEGMENT ← SEGMENT & "_" ;
					IF R THEN INPUTSTR ← "_" & INPUTSTR ;
					GO TO FORMAL ;
					END ;
				END "MAYBE UNDERLINED" ;
		SEGMENT ← SEGMENT & IDENT ;
		END "LETTER"
	ELSE SEGMENT ← SEGMENT & BRC ;
	STBL[SINDX ← SINDX+1] ← SEGMENT ; 
	IF SINDX = SHIGH+20 THEN
		BEGIN
		SEGMENT ← STBL[SHIGH + 1] ;
		FOR I ← SHIGH + 2 THRU SINDX DO BEGIN SEGMENT ← SEGMENT & STBL[I] ; STBL[I]←NULL; END;
		SINDX ← SHIGH + 1 ; STBL[SINDX] ← SEGMENT ;
		IF DEEP THEN TES 8/19/74 CHECK FOR INFINITE TEMPLATE ;
			IF LENGTH(SEGMENT) > MAXTEMPLATE THEN
				BEGIN
				WARNLONG(SEGMENT, "A template is longer than " &
    				CVS(MAXTEMPLATE) & " characters" & CRLF &
    				"If you really have such a long one, increase the value of maxtemplate") ;
				STBL[SINDX] ← NULL ; DONE ;
				END
			ELSE IF PAGEMARKS > PGMKS THEN
				BEGIN
				WARNLONG(SEGMENT,
					"A template crosses a manuscript page mark (form feed)") ;
				STBL[SINDX] ← NULL ; DONE ;
				END
			ELSE IF LAST NEQ REQRS THEN
				BEGIN
				WARNLONG(SEGMENT, "A template crosses a file boundary (eof)") ;
				STBL[SINDX] ← NULL ; DONE ;
				END ;
		END ;
	END "DEF BODY" ;
SEGMENT ← STBL[SHIGH+1] ; FOR I ← SHIGH+2 THRU SINDX DO SEGMENT ← SEGMENT & STBL[I] ;
IF FORFILE THEN SEGMENT ← SEGMENT & LF ;
 DEFINING ← FALSE ; INPUTSTR ← ";" & INPUTSTR ; PASS ;
RETURN(SEGMENT) ;
END "DEFN" ;
PUBLIC SIMPLE PROCEDURE DMACRO(INTEGER ODDONE) ;$"#
TES 8/19/74 ODDONE= 0:RECURSIVE MACRO 1:MACRO 2:PROCEDURE;
BEGIN COMMENT, OLD VERSION NOT GARBAGED BUT COULD BE ;
INTEGER SIHIGH, MIX, ARGS, J, NAMES, NAME ; BOOLEAN ROTTEN ;
SIHIGH ← IHIGH ; DPASS ; IF  NOT THISISID THEN BEGIN WARN("=","Macro name not identifier") ; RETURN END ;
IF THATISID THEN BEGIN "TWO WORD" THISWD ← THISWD & SP & THATWD ; RDENTITY ; END "TWO WORD" ;
PUTI(1, SYMNUM(THISWD)) ; PASS ;
IF ITSCH(<(>) THEN
BEGIN "FORMALS"
ROTTEN ← FALSE ; THISWD ← "," ; NAMES ← 0 ;
DO	BEGIN
	IF ITSCH(<,>) THEN DPASS
	ELSE BEGIN WARN("=","Missed comma in macro formal list") ; ROTTEN←TRUE END ;
	IF ITSCH(ε) THEN BEGIN DPASS ; NAME ← 0 ; END ELSE NAME ← 1 ;
	IF  NOT THISISID THEN BEGIN WARN("=","Formal parameters must be identifiers") ; ROTTEN←TRUE END
	ELSE BEGIN PUTI(1, SYMB) ; NAMES ← 2*NAMES + NAME ; DPASS END ;
	END
UNTIL ITSCH(<)>) OR ROTTEN ;
IF ITSCH(<)>) THEN PASS ;
END "FORMALS" ;
IF ROTTEN OR  NOT ON THEN BEGIN IHIGH ← SIHIGH ; DEFN(FALSE, FALSE,0,0) ; RETURN END ;
ARGS ← IHIGH - SIHIGH - 1 ; BIND(DECLARE(ITBL[SIHIGH+1], MACROTYPE), MIX←PUSHI(MACROWDS,MACROTYPE)) ;
NUMARGS(MIX) ← ARGS ; ODDMAC(MIX) ← ODDONE ; BODY(MIX) ← PUSHS(1,DEFN(FALSE, FALSE,ARGS,SIHIGH+1)) ;
IHIGH ← SIHIGH ; NAMEPAR(MIX) ← NAMES ;
END "DMACRO" ;
PUBLIC SIMPLE PROCEDURE DREPEAT ;$"#
BEGIN TES 8/14/74 ;
STRING BOD ;
PASS ;
BOD ← DEFN(FALSE, FALSE, 0, 0) ;
IF ON THEN
	BEGIN
	DEEPREPEATS ← DEEPREPEATS + 1 ;
	SWICH(BOD, -2-BLNMS, 0) ;
	SWICH(BOD, -1, 0) ;
	PASS ;
	END ;
END "DREPEAT" ;
PUBLIC RECURSIVE STRING PROCEDURE PROCSTATEMENT ;$"#
    IF THISTYPE = MACROTYPE THEN
	IF ODDMAC(IX)<2 THEN WARN(NULL,<"Unexpanded MACRO "&THISWD&" (PUB Bug)">)
	ELSE IF ON THEN
		BEGIN
		INTEGER PR ;
		PR←DEEPPROCEDURES←DEEPPROCEDURES+1;
		APPLYTOARGUMENTS(TRUE, TRUE);
		DO STATEMENT UNTIL DEEPPROCEDURES<PR;
		RETURN(TRUE) ;
		END
	ELSE	BEGIN
		APPLYTOARGUMENTS(FALSE, FALSE) ;
		RETURN(TRUE) ;
		END
    ELSE RETURN(FALSE) ;
PUBLIC SIMPLE PROCEDURE WARNLONG(STRING SEGM, MESG) ;$"#
	WARN(NULL, <MESG & CRLF &
		"[You probably omitted a template closer: )$ or ↑P or Horseshoe]"
		& CRLF & "The template began with:" & CRLF & SEGM[1 TO 70]>) ;
FINISHED

ENDOF("TEMPL")